package com.jotta.client;

import java.io.File;
import java.util.ArrayList;

import android.app.AlertDialog;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;

import com.jotta.client.communicate.Configuration;
import com.jotta.client.communicate.ModeOfBrowse;
import com.jotta.client.communicate.ModeOfSeverCommunicate;
import com.jotta.client.communicate.ServerCommunicator;
import com.jotta.client.communicate.StateOfClient;
import com.jotta.client.data.DeviceInfo;
import com.jotta.client.data.FileInfo;
import com.jotta.client.data.ItemAdapter;
import com.jotta.client.data.ItemInfo;
import com.jotta.client.data.TypeOfDevice;
import com.jotta.client.data.TypeOfItem;
import com.jotta.client.dataaccess.DataAccess;
import com.jotta.client.exception.NetworkException;
import com.jotta.client.exception.ServerException;
import com.jotta.client.setting.ModeOfApplication;
import com.jotta.client.setting.SettingManager;
import com.jotta.client.utility.Utility;

public class ListItem extends ListActivity implements OnItemClickListener, Runnable {

    private ItemAdapter adapter;
    private ServerCommunicator communicator;
    private ProgressDialog m_ProgressDialog;
    private ItemInfo selectedItem;
    public static String TAG = "JOTTA_LISTITEM";


    @Override
    public void onCreate(Bundle savedInstanceState) {
        try {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.list_item);

            Configuration.prepareConfiguration(this);
            DataAccess.getInstance().initializeDatabase(this);
            Configuration.setStateOfClient(StateOfClient.OFFLINE);

            communicator = ServerCommunicator.getInstance();
            DataAccess.getInstance().initializeDatabase(ListItem.this);
            ArrayList<ItemInfo> folderInfo = communicator.getFolderInfo();

            if ((folderInfo == null) || folderInfo.isEmpty()) {
                startThreadToRestart();
            } else {
                this.adapter = new ItemAdapter(this, R.layout.row, folderInfo);
                setListAdapter(this.adapter);

                ListView lv = getListView();
                lv.setOnItemClickListener(this);

                updateCurrentTitle();
            }
        } catch (Exception e) {
            //Log.e(TAG, "On create error", e);
        }
    }

    /*
      * (non-Javadoc) Must stop download thread from here
      *
      * @see android.app.Activity#onStop()
      */
    @Override
    protected void onStop() {
        SettingManager.getInstance().setLatestBrowsePath(ServerCommunicator.getInstance().getCurrentPath());

        if (Configuration.getStateOfClient() == StateOfClient.DOWNLOADING) {
            Configuration.setStateOfClient(StateOfClient.CANCEL_DOWNLOAD);
        }

        super.onStop();
    }

    public void onItemClick(AdapterView<?> parent, View view, int position,
                            long arg3) {
        selectedItem = adapter.getItem(position);

        if ((selectedItem instanceof FileInfo)) {
            FileInfo fileInfo = (FileInfo) selectedItem;
            if (donwloadFilePreProcessing(fileInfo)) {
                if (fileInfo.getFileSize() > SettingManager.getInstance()
                        .getLocalFreeSpace()) {
                    showNotEnoughFreeSpaceDialog(fileInfo);
                } else {
                    Configuration
                            .setModeOfSeverCommunicate(ModeOfSeverCommunicate.DOWNLOAD);
                    startThread2DownloadFile();
                }
            } else {
                if (Configuration.getModeOfApplication() == ModeOfApplication.FULL_OPTION) {
                    Utility.showFileManipulateDialog(ListItem.this, fileInfo,
                            fileInfo.getLocalPathOfItem());
                }
            }
        } else {
            startThreadToGetServerInfomation(ModeOfBrowse.FORWARD);
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            startThreadToGetServerInfomation(ModeOfBrowse.BACK);
            return true;
        } else {
            return super.onKeyDown(keyCode, event);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.list_item_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.list_item_menu_home:
                startThreadToGetServerInfomation(ModeOfBrowse.HOME);
                return true;
            case R.id.list_item_menu_back:
                startThreadToGetServerInfomation(ModeOfBrowse.BACK);
                return true;
            case R.id.list_item_menu_logout:
                logOut();
                return true;
            case R.id.list_item_menu_quit:
                quit();
                return true;
            case R.id.list_item_menu_setting:
                startSettingActivity();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    private void startSettingActivity() {
        Intent intent = new Intent();
        intent.setClass(getApplicationContext(), Setting.class);
        startActivity(intent);
    }

    private void logOut() {
        ServerCommunicator.getInstance().shutdown();
        SettingManager.getInstance().resetUserInfo();

        Intent intent = new Intent();
        intent.setClass(getApplicationContext(), Login.class);
        startActivity(intent);
        if (Configuration.getStateOfClient() == StateOfClient.DOWNLOADING) {
            Configuration.setStateOfClient(StateOfClient.CANCEL_DOWNLOAD);
        }
        finish();
    }

    private void quit() {
        ServerCommunicator.getInstance().shutdown();
        if (Configuration.getStateOfClient() == StateOfClient.DOWNLOADING) {
            Configuration.setStateOfClient(StateOfClient.CANCEL_DOWNLOAD);
        }
        finish();
    }

    /**
     * Pre processing to download file
     *
     * @return true: start download file - false: do not allow to download
     */
    private boolean donwloadFilePreProcessing(FileInfo fileInfo) {
        boolean result = false;
        if (Configuration.getModeOfApplication() == ModeOfApplication.BROWSE) {
            String message = getResources().getString(
                    R.string.browse_mode_message);
            Utility.getAlertDialog(ListItem.this, getResources(), message)
                    .show();
            result = false;
        } else if (!DataAccess.getInstance().checkSDCardIsMounted()) {
            String message = getResources().getString(
                    R.string.browse_mode_message);
            Utility.getAlertDialog(ListItem.this, getResources(), message)
                    .show();
            Configuration.setModeOfApplication(ModeOfApplication.BROWSE);
            result = false;
        } else {
            String localFilePath = fileInfo.getLocalPathOfItem();
            File file = new File(localFilePath);
            if (file.exists() && file.length() == fileInfo.getFileSize()) {
                int latestRevionOfFile = DataAccess.getInstance()
                        .getLatestRevisionOfFile(localFilePath);
                int currentRevisionOfFile = fileInfo.getCurrentRevionsNumber();
                if (latestRevionOfFile != currentRevisionOfFile) {
                    result = true;
                } else {
                    result = false;
                }
            } else {
                result = true;
            }
        }
        return result;
    }

    private void startThread2DownloadFile() {
        if ((Configuration.getModeOfSeverCommunicate() == ModeOfSeverCommunicate.DOWNLOAD)
                || (Configuration.getModeOfSeverCommunicate() == ModeOfSeverCommunicate.DOWNLOAD_WITH_AUTO_DELETE)) {
            Thread thread = new Thread(this);
            thread.start();

            // initialize progress bar
            m_ProgressDialog = Utility.getProgressBar(ListItem.this,
                    Configuration.getRes()
            );
            m_ProgressDialog.show();
        }
    }

    private void showNotEnoughFreeSpaceDialog(ItemInfo itemInfo) {
        String autoDelete = Configuration.getRes().getString(
                R.string.auto_delete_free_space_dialog);

        String cancel = Configuration.getRes().getString(
                R.string.cancel_free_space_dialog);
        final CharSequence[] items = {autoDelete, cancel};
        AlertDialog.Builder builder = new AlertDialog.Builder(ListItem.this);
        builder.setTitle(Configuration.getRes().getString(
                R.string.not_enough_free_space_dialog_header));

        builder.setItems(items, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int item) {
                if (item == 0) {
                    Configuration
                            .setModeOfSeverCommunicate(ModeOfSeverCommunicate.DOWNLOAD_WITH_AUTO_DELETE);
                    startThread2DownloadFile();
                }
            }
        });

        AlertDialog alert = builder.create();
        alert.show();
    }

    /**
     * Start new thread to login when activity is restart
     */
    private void startThreadToRestart() {
        Configuration.setModeOfSeverCommunicate(ModeOfSeverCommunicate.RESTART);
        Configuration.setModeOfBrowse(ModeOfBrowse.FORWARD);
        Thread thread = new Thread(this);
        thread.start();

        // initialize progress bar
        m_ProgressDialog = Utility.getProgressBar(ListItem.this,
                Configuration.getRes());
        m_ProgressDialog.show();
    }

    /**
     * Start new thread to get information from server & show progress bar
     *
     * @param mode Mode of browse
     */
    private void startThreadToGetServerInfomation(ModeOfBrowse mode) {
        Configuration
                .setModeOfSeverCommunicate(ModeOfSeverCommunicate.GET_SERVER_INFOMATION);
        Configuration.setModeOfBrowse(mode);
        Thread thread = new Thread(this);
        thread.start();

        // initialize progress bar
        m_ProgressDialog = Utility.getProgressBar(ListItem.this,
                Configuration.getRes());
        m_ProgressDialog.show();
    }

    /*
      * Get data from server & notified to handler when finished
      *
      * @see java.lang.Runnable#run()
      */
    public void run() {
        if (Configuration.getModeOfSeverCommunicate() == ModeOfSeverCommunicate.GET_SERVER_INFOMATION) {
            getServerInformation();
        } else if (Configuration.getModeOfSeverCommunicate() == ModeOfSeverCommunicate.RESTART) {
            getServerInformation();
        } else if (Configuration.getModeOfSeverCommunicate() == ModeOfSeverCommunicate.DOWNLOAD) {
            downloadFileFromSever();
        } else if (Configuration.getModeOfSeverCommunicate() == ModeOfSeverCommunicate.DOWNLOAD_WITH_AUTO_DELETE) {
            if (selectedItem instanceof FileInfo) {
                FileInfo fileInfo = (FileInfo) selectedItem;
                Configuration
                        .setStateOfClient(StateOfClient.AUTO_DELETE_SERVICE);
                if (DataAccess.getInstance().autoDeleteService(
                        fileInfo.getFileSize())) {
                    downloadFileFromSever();
                } else {
                    autoDeleteNotSuccessHandler.sendEmptyMessage(0);
                    Configuration.setStateOfClient(StateOfClient.OFFLINE);
                }
            } else {
                String message = Configuration.getRes().getString(
                        R.string.selected_item_is_not_file);
                Bundle bundle = new Bundle();
                bundle.putString(Configuration.CLIENT_ERROR_MESSAGE_KEY,
                        message);
                Message msg = new Message();
                msg.setData(bundle);
                dismissProgressBarHandler.sendMessage(msg);
            }
        }
    }

    private void downloadFileFromSever() {
        Configuration.setStateOfClient(StateOfClient.DOWNLOADING);
        Bundle bundle = new Bundle();

        Message msg = new Message();
        String serverMessage = "";
        try {
            communicator = ServerCommunicator.getInstance(ListItem.this.updateProgressBarHandler);
            if (selectedItem instanceof FileInfo) {
                FileInfo fileInfo = (FileInfo) selectedItem;
                String downloadPath = fileInfo.getDownloadPathOfItem();
                String filePath = fileInfo.getServerPathOfItem();
                long fileSize = fileInfo.getFileSize();

                communicator.downloadFile(downloadPath, filePath, fileSize);

                serverMessage = Configuration.GET_DATA_SUCCESSFUL_MESSAGE;

            }

        } catch (ServerException e) {
            serverMessage = e.getErrorMessage();
        } catch (NetworkException e) {
            serverMessage = e.getErrorMessage();
        } catch (Exception e) {
            if (e.getMessage() != null){
                serverMessage = e.getMessage();
            }else{
                serverMessage = e.toString();
            }
        }

        bundle.putString(Configuration.SERVER_MESSAGE_KEY, serverMessage);
        msg.setData(bundle);
        downloadedHandler.sendMessage(msg);

        Configuration.setStateOfClient(StateOfClient.OFFLINE);

    }

    private void getServerInformation() {
        Configuration.setStateOfClient(StateOfClient.GETTING_SERVER_INFORMATION);

        String message = "";
        if (Configuration.getModeOfSeverCommunicate() == ModeOfSeverCommunicate.RESTART) {
            message = restart();

        } else if (Configuration.getModeOfSeverCommunicate() == ModeOfSeverCommunicate.GET_SERVER_INFOMATION) {
            if (Configuration.getModeOfBrowse() == ModeOfBrowse.FORWARD) {
                message = browseFolder();

            } else if (Configuration.getModeOfBrowse() == ModeOfBrowse.BACK) {
                message = goBack();

            } else if (Configuration.getModeOfBrowse() == ModeOfBrowse.HOME) {
                message = goHome();

            }
        }

        Bundle bundle = new Bundle();
        bundle.putString(Configuration.SERVER_MESSAGE_KEY, message);
        Message msg = new Message();
        msg.setData(bundle);

        getInformationFinishedHandler.sendMessage(msg);
        Configuration.setStateOfClient(StateOfClient.OFFLINE);
    }

    /**
     * Log in
     *
     * @return Message from server
     */
    private String restart() {
        try {
            String username = SettingManager.getInstance().getUsername();
            String password = SettingManager.getInstance().getPassword();

            String latestPath = SettingManager.getInstance().getLatestBrowsePath();

            communicator = ServerCommunicator.getInstance(ListItem.this.updateProgressBarHandler);
            communicator.restart(username, password, latestPath);

            return Configuration.GET_DATA_SUCCESSFUL_MESSAGE;


        } catch (ServerException e) {
            return e.getErrorMessage();
        } catch (NetworkException e) {
            return e.getErrorMessage();
        } catch (Exception e) {

            if (e.getMessage() != null)
                return e.getMessage();
            return e.toString();
        }
    }

    /**
     * Go back
     *
     * @return Message from server
     */
    private String goBack() {
        try {
            communicator = ServerCommunicator.getInstance(ListItem.this.updateProgressBarHandler);

            communicator.goBack();
            return Configuration.GET_DATA_SUCCESSFUL_MESSAGE;
        } catch (ServerException e) {
            return e.getErrorMessage();
        } catch (NetworkException e) {
            return e.getErrorMessage();
        } catch (Exception e) {
            if (e.getMessage() != null)
                return e.getMessage();
            return e.toString();
        }
    }

    /**
     * Go home
     *
     * @return Message from server
     */
    private String goHome() {
        try {
            communicator = ServerCommunicator.getInstance(ListItem.this.updateProgressBarHandler);
            communicator.goHome();

            return Configuration.GET_DATA_SUCCESSFUL_MESSAGE;
        } catch (ServerException e) {
            return e.getErrorMessage();
        } catch (NetworkException e) {
            return e.getErrorMessage();
        } catch (Exception e) {
            if (e.getMessage() != null)
                return e.getMessage();
            return e.toString();
        }
    }

    /**
     * Browse Folder
     *
     * @return Message from server
     */
    private String browseFolder() {

        try {
            communicator = ServerCommunicator.getInstance(ListItem.this.updateProgressBarHandler);
            TypeOfItem typeOfItem = selectedItem.getType();

            if (typeOfItem == TypeOfItem.FOLDER || typeOfItem == TypeOfItem.MOUNTPOINT) {
                communicator.browseFolder(selectedItem.getTitle(), false);

            } else if (typeOfItem == TypeOfItem.DEVICE) {

                DeviceInfo deviceInfo = (DeviceInfo) selectedItem;

                if (deviceInfo.getTypeOfDevice() == TypeOfDevice.JOTTA) {
                    communicator.browseFolder(deviceInfo.getTitle(), true);
                } else {
                    communicator.browseFolder(selectedItem.getTitle(), false);
                }

            }

            return Configuration.GET_DATA_SUCCESSFUL_MESSAGE;

        } catch (ServerException e) {
            return e.getErrorMessage();
        } catch (NetworkException e) {
            return e.getErrorMessage();
        } catch (Exception e) {
            return e.getMessage();
        }
    }


    private void updateCurrentFolderInfo() {

        ArrayList<ItemInfo> folderInfo = communicator.getFolderInfo();


        if (this.adapter == null) {
            this.adapter = new ItemAdapter(this, R.layout.row, folderInfo);
            setListAdapter(this.adapter);

            ListView lv = getListView();
            lv.setOnItemClickListener(this);
        } else {
            this.adapter.updateItemInfoList(folderInfo);
            this.setSelection(0);
        }
        updateCurrentTitle();
    }

    private void updateCurrentTitle() {
        String app_name = Configuration.getRes().getString(R.string.app_name);
        setTitle(app_name + " - " + communicator.getCurrentFolder());
    }


    /**
     * update progress of progress bar
     */
    private Handler updateProgressBarHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {

            int progress = msg.getData().getInt(Configuration.PROGRESS_BAR_PERCENT);
            String downloadHeader = msg.getData().getString(Configuration.DOWNLOAD_HEADER);

            if (m_ProgressDialog != null) {
                m_ProgressDialog.setProgress(progress);
                m_ProgressDialog.setMessage(downloadHeader);
            }
        }
    };

    /**
     * Dismiss progress bar handler
     */
    private Handler dismissProgressBarHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            m_ProgressDialog.setProgress(100);
            m_ProgressDialog.dismiss();
        }
    };

    /**
     * When auto delete service not success dismiss progress dialog, and showing
     * the aler dialog
     */
    private Handler autoDeleteNotSuccessHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            m_ProgressDialog.setProgress(100);
            m_ProgressDialog.dismiss();
            Utility.getAlertDialog(ListItem.this,Configuration.getRes(),
                    Configuration.getRes().getString(R.string.auto_service_not_sucess)).show();
        }
    };

    /**
     * When download file from server finished dismiss progress dialog
     */
    private Handler downloadedHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            m_ProgressDialog.dismiss();
            String message = msg.getData().getString(Configuration.SERVER_MESSAGE_KEY);

            if (!message.equals(Configuration.GET_DATA_SUCCESSFUL_MESSAGE)) {
                Utility.getAlertDialog(ListItem.this, Configuration.getRes(), message).show();

            } else {
                FileInfo fileInfo = (FileInfo) selectedItem;
                DataAccess.getInstance().recordNewFileIntoDatabase(fileInfo);
                Utility.showFileManipulateDialog(ListItem.this, fileInfo,fileInfo.getLocalPathOfItem());
            }
        }
    };

    /**
     * When load data from server finished dismiss progress dialog
     */
    private Handler getInformationFinishedHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            m_ProgressDialog.dismiss();
            String message = msg.getData().getString(Configuration.SERVER_MESSAGE_KEY);
            if (message == null || !message.equals(Configuration.GET_DATA_SUCCESSFUL_MESSAGE)) {
                Utility.getAlertDialog(ListItem.this, Configuration.getRes(),message).show();
            } else {
                updateCurrentFolderInfo();
            }
        }
    };

}
